<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <script type="text/javascript" src="./lib/vue-2.4.0.js"></script>
    <link rel="stylesheet" type="text/css" href="./lib/bootstrap-3.3.7.css" />
    <!-- 需要用到Jquery吗？？？ -->
  </head>

  <body>
    <div id="app">
      <div class="panel panel-primary">
        <div class="panel-heading">
          <h3 class="panel-title">添加品牌</h3>
        </div>
      </div>

      <div class="panel-body form-inline">
        <label>
          Id:
          <input type="text" class="form-control" v-model="id" />
        </label>

        <label>
          Name:
          <!-- 按键修饰符 指定特定哪个键盘按键触发事件 -->
          <input
            type="text"
            class="form-control"
            v-model="name"
            @keyup.f2="add"
          />
        </label>

        <!-- 在Vue中使用事件绑定机制，为元素指定处理函数的时候，如果加了小括号，就可以给函数传参了 -->
        <input
          type="button"
          value="添加"
          class="btn btn-primary"
          @click="add()"
        />

        <label>
          搜索名称关键字:
          <!-- 注意：Vue中所有的指令，在调用的时候，都以 v- 开头 -->
          <input
            type="text"
            class="form-control"
            v-model="keywords"
            id="search"
            v-focus
            v-color="'yellow'"
          />
        </label>
      </div>

      <table class="table table-bordered table-hover table-striped">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Ctime</th>
            <th>Operation</th>
          </tr>
        </thead>

        <tbody>
          <tr v-for="item in search(keywords)" :key="item.id">
            <td>{{ item.id }}</td>
            <td v-text="item.name"></td>
            <td>{{ item.ctime | dateFormat() }}</td>
            <td>
              <a href="" @click.prevent="del(item.id)">删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

    <div id="app2">
      <h3 v-color="'pink'" v-fontweight="900" v-fontsize="50">
        {{ dt | dateFormat }}
      </h3>
    </div>
    <script type="text/javascript">
      // 全局过滤器，进行时间的格式化
      // 所谓的全局过滤器，就是所有的VM实例控制区域都共享的  不带有 s 只实现一个功能  只有私有的带有 s 实现多个功能    // es6新语法  形参数默认值
      Vue.filter("dateFormat", function(dateStr, pattern = "") {
        // 根据给定的时间字符串，得到特定的时间
        var dt = new Date(dateStr);

        // yyyy-mm-dd
        var y = dt.getFullYear();
        var m = dt.getMonth() + 1;
        var d = dt.getDate(0);

        // return y + '-' + m + '-' + d;

        if (pattern.toLowerCase() === "yyyy-mm-dd") {
          return `${y}-${m}-${d}`;
        } else {
          var hh = dt.getHours();
          var mm = dt.getMinutes();
          var ss = dt.getSeconds();

          return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
        }
      });

      // 自定义全局按键修饰符 给键盘码113 取别名为 f2
      Vue.config.keyCodes.f2 = 113;

      // 使用 Vue.directive() 定义全局的指令 v-focus 调用使用v-focus指令调用
      // 其中：参数1： 指令的名称，注意，在定义的时候，指令的名称前面，不需要加 v- 前缀，  系统默认自动会加v-前缀
      // 但是，在调用的时候，必须 在指令名称前 加上 v- 前缀来进行调用
      // 参数2：是一个对象，在这个对象身上，有一些指令相关的函数(钩子函数)，这些函数可以在特定的阶段，执行相关的操作

      Vue.directive("focus", {
        // 指令一加到元素上时就会执行bind 此时元素还没插入到 dom 中
        // 浏览器界面上任何元素 想要显示 必须经过浏览器渲染引擎 解析元素
        // 把解析好的元素先放到浏览器内存的 dom 树里  如果还没放到浏览器内存的dom树里面
        // 只属于浏览器内存里面的东西不能获取焦点  只有放到页面(浏览器的内存)上才能获取焦点(浏览器才能渲染出来)

        //  指令一加到元素上时就会执行bind 此时元素还没插入到 dom 中
        bind: function(el) {
          // 每当指令绑定到元素上的时候，会立即执行这个 bind 函数 只执行一次 因为一个指令交给一个元素绑定只能绑定一次  bind也只能执行一次
          //  指令刚一加给元素就执行bind
          //注意：在每个函数中，第一个参数，永远是 el， 表示 被绑定了指令那个原生dom元素，
          //这个el参数 是一个原生的JS对象(dom对象)
          //在元素 刚绑定了指令的时候，还没有 插入到浏览器内存的 DOM 中去，这时候，调用 focus方法没有作用
          // 因为一个元素，只有插入DOM之后，才能获取焦点
          // el.focus();
          //  在浏览器内存中获得焦点无意义  就算获得焦点后  最终从 浏览器的内存中 插入到 浏览器内存的 dom中去
          //  而插入时要创建一下这个元素 不会再执行这个 focus  只有插入到浏览器内存的 dom 树后执行 才会在界面上生效
        },
        inserted: function(el) {
          // inserted 表示元素 插入到 DOM之后，会执行inserted函数【触发一次】
          el.focus(); // 这是 js的行为  只有在浏览器内存的dom中才能获得焦点

          // 和 JS 行为相关的操作，最好在 inserted 中去执行，防止  JS 行为不生效
        },
        updated: function(el) {
          //当VNode(组件)  或dom节点更新的时候，会执行updated，可能会触发多次
        }
      });

      //自定义一个 设置字体颜色的指令
      Vue.directive("color", {
        // 样式，只要通过指令绑定给了元素，不管这个元素有没有被插入到页面(浏览器内存的dom)中去，这个元素肯定有了一个内联的样式
        // 将来元素肯定会显示到页面中，这时候，浏览器的渲染引擎必然会解析样式，应用给这个元素

        // 先是在浏览器内存中浏览器渲染引擎解析元素   然后插入到 （页面）浏览器内存的dom树
        bind: function(el, binding) {
          // bind 执行时机早于 inserted
          // el.style.color = 'red';  // 设置样式不用关心有没有插入到dom中去  只要把样式设置到dom元素   浏览器渲染引擎解析dom时
          // 自然会解析dom身上的样式 然后从浏览器的内存插入到 浏览器内存的 dom树中 显示到界面上时自然会把样式应用起来  相当于 元素跟样式捆绑
          // console.log(binding.name);
          // 和样式相关的操作，一般都可以在 bind 执行

          // dinging.value 获取指令绑定的表达式计算后的结果
          // dinging.expression 获取指令绑定的表达式原样输出

          // console.log( binding.value );
          // console.log( binding.expression ;

          el.style.color = binding.value;
        }
      });

      // 创建 Vue实例，得到 ViewModel
      var vm = new Vue({
        el: "#app",
        data: {
          id: "",
          name: "",
          keywords: "",
          list: [
            { id: 1, name: "奔驰", ctime: new Date() },
            { id: 2, name: "宝马", ctime: new Date() }
          ]
        },
        methods: {
          add() {
            // 添加的方法
            // console.log('ok');
            // 分析：
            // 1.获取到 id 和 name，直接从data上面获取
            // 2.组织出一个对象
            // 3.把这个对象，调用 数组的 相关方法，添加到 当前 data 上的list中
            // 4.注意：在Vue中，已经实现了数据的双向绑定，每当我们修改了 data 中的数据，Vue会默认监听到数据的改动，自动把最新的数据，应用到页面上；
            // 5. 当我们意识到上面的第四步的时候，就证明大家已经入门Vue了，我们更多的是在进行 VM中 Model 数据的操作，同时，在操作Model数据的时候，指定的业务逻辑操作；

            var car = { id: this.id, name: this.name, ctime: new Date() };
            this.list.push(car);
            this.id = this.name = "";
          },
          search(keywords) {
            //根据关键字，进行数据搜索
            /*var newList = [];
                    this.list.forEach((item)=>{
                        if( item.name.indexOf(keywords) != -1){
                            newList.push(item);
                        }
                    });
                    return newList;*/

            // 注意： forEach some filter findIndex 这些都属于数组的新方法，
            // 都会对数组中的每一项，进行遍历，执行相关的操作;
            return this.list.filter(item => {
              if (item.name.includes(keywords)) {
                return item;
              }
            });

            // return newList;
          },
          del(id) {
            // 分析：
            // 1.如何根据Id,找到要删除这一项的索引
            // 2.如果找到索引了，直接调用 数组的 splice 方法

            /*this.list.some((item, i)=>{
                        if( item.id == id ){
                            this.list.splice(i ,1);
                            // 在数组的 some 方法中 ，如果 return true, 就会立即终止这个数组的后续循环
                            return true;
                        }
                    });*/

            var index = this.list.findIndex(item => {
              if (item.id == id) {
                return true;
              }
            });

            // console.log(index);
            this.list.splice(index, 1);
          }
        }
      });

      // 如何自定义一个私有的过滤器(  局部 )
      var vm2 = new Vue({
        el: "#app2",
        data: {
          dt: new Date()
        },
        methods: {},
        filters: {
          // 定义私有过滤器(可以有多个)  过滤器有两个 条件 【过滤器名称 和 处理函数】
          //过滤器调用的时候，采用的是就近原则，如果私有过滤器和全局过滤器名称一致了，这时候 优先调用私有过滤器
          dateFormat: function(dateStr, pattern = "") {
            console.log(typeof dateStr);
            // 根据给定的时间字符串，得到特定的时间
            var dt = new Date(dateStr);

            // yyyy-mm-dd
            var y = dt.getFullYear();
            var m = (dt.getMonth() + 1).toString().padStart(2, 0);
            var d = dt
              .getDate(0)
              .toString()
              .padStart(2, 0);

            // return y + '-' + m + '-' + d;

            if (pattern.toLowerCase() === "yyyy-mm-dd") {
              return `${y}-${m}-${d}`;
            } else {
              var hh = dt
                .getHours()
                .toString()
                .padStart(2, 0);
              var mm = dt
                .getMinutes()
                .toString()
                .padStart(2, 0);
              var ss = dt
                .getSeconds()
                .toString()
                .padStart(2, 0);

              return `${y}-${m}-${d} ${hh}:${mm}:${ss}~~~`;
            }
          }
        },

        directives: {
          // 自定义私有指令 带s 可以实现多个功能  指令有两个条件 【指令名称 和 指令处理相关对象】
          fontweight: {
            // 设置字体粗细
            bind: function(el, binding) {
              el.style.fontWeight = binding.value;
            }
          },
          fontsize: function(el, binding) {
            // 注意：这个 function 等同于 把 代码写到了 bind 和 updated 中去
            // 相当于在 bind和 updated 函数体中都写了一份相同代码
            el.style.fontSize = parseInt(binding.value) + "px";
          }
        }
      });

      // 过滤器的定义语法 参数二表示对传过来的数据做相应处理  过滤器不修改原数据  只是中间做了一层处理
      // Vue.filter('过滤器的名称', function(){})

      // 过滤器中的 function， 第一个参数，已经被规定死了，永远都是 过滤器 管道符前面 传递过来的数据
      /* Vue.filter('过滤器的名称', function( data ){
             return data +'123';
         })*/
    </script>
  </body>
</html>

<!-- 过滤器调用时的格式 {{ name | 过滤器的名称 }}
     表示输出name值之前调用过滤器进行处理， 把name值传递给后面过滤器，
     处理过程就是函数调用过程，并把处理的结果当作内容渲染到当前位置 -->
